
/* 
* sepmpi.h - This file is a part of the sep-library 
*
* Copyright (C) 2008 Jesper Schmidt Hansen 
* 
* License: GPL - see COPYING for copying conditions.
* There is ABSOLUTELY NO WARRANTY, not even for MERCHANTIBILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* Contact: schmidt@zigzak.net
*/



#ifndef __SEPMPI_H__
#define __SEPMPI_H__

#include "mpi.h"
#include "sep.h"
#include "sepmpitype.h"

#ifndef DOXYGEN_SKIP
enum tags {
	   SEP_MSGTAG_IDLEFT=100, SEP_MSGTAG_IDRIGHT=200, 
	   SEP_MSGTAG_NPART1=10, SEP_MSGTAG_NPART2=20, 
	   SEP_MSGTAG_PART1=30, SEP_MSGTAG_PART2=40, 
	   SEP_MSGTAG_POS1=3, SEP_MSGTAG_POS2=4, 
	   SEP_MPI_SAVE_XYZ=22 
};
#endif


/* Initialise */

/**
 * Initialising structure and sets many system specifics.
 * @param maxpart Maximum number of particles each process
 * can have - note this includes virtual and physical particles.
 * @param nx Initial number of particles in the x-direction
 * @param ny Initial number of particles in the y-direction
 * @param nz Initial number of particles in the z-direction
 * @param cf Maximum cut-off length
 * @param dens Average density of the system
 * @return sepmpi pointer contianing relevant information.  
 */
sepmpi *sep_mpi_init(long int maxpart, int nx, int ny, 
		     int nz, double cf, double dens);


/* Perform domian composition (every ten time step or so), 
   exchange particle info (every time step) and make neighbourlist if
   required. Finally wrap every thing into a nice function call */
#ifndef DOXYGEN_SKIP
void sep_mpi_get_xv(seppart *ptr, sepmpi *mpip);
//void sep_mpi_set_vel(seppart *ptr, double temp, int npart, int ndim);

void sep_mpi_set_id(seppart *ptr, sepmpi *mpip);		

void sep_mpi_exchange_pos(seppart *ptr, sepmpi *mpip);
void sep_mpi_exchange_part(seppart *ptr, sepmpi *mpip);

int *sep_mpi_allocate_celllist(sepmpi *mpip);
void sep_mpi_make_celllist(seppart *ptr, int *list, sepmpi *mpip);
void sep_mpi_make_neighblist(seppart *ptr,  double dx, int nneighb,
			     int *list, sepmpi *mpip);
void sep_mpi_neighb(seppart *ptr, sepmpi *mpip);
#endif

/**
 * Exchange relevant information between processes. If n%mod is 
 * zero the particles are positioned in the process that handle the
 * domain in which it is located (domain decompositon). 
 * Otherwise simple informations such as positions is exchanged 
 * between the processes. Usually mod = 10 is fine. 
 * @param *ptr Pointer to array of seppart structures
 * @param *mpip Pointer to the sepmpi struture
 * @param n Step number Must start from zero and incremented after
 * each time step.
 * @param mod Interger indecating how often the domain decompostion
 * is to be carried out
 */
void sep_mpi_parallel(seppart *ptr, sepmpi *mpip, int n, 
		      const int mod);


/* Force calculations */

/**
 * Calculating the pair-forces acting between all particles.
 * @param *ptr Pointer to array of seppart structure
 * @param *fun Pointer to the pair potential function. Note that the 
 * cut-off length specified in the sep3D structure is used.
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
  */
double sep_mpi_force_pair(seppart *ptr, double (*fun)(double, char), 
			  sepmpi *mpip);


/**
 * Calculating the pair-forces acting between particles of specific 
 * types
 * @param *ptr Pointer to array of seppart structure
 * @param *types String specifying the TWO particles type
 * @param *fun Pointer to the pair potential function
 * @param cf  The cut-off length
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
  */
double sep_mpi_force_pair_types(seppart *ptr,  const char *types, 
				double cf, double (*fun)(double, char), 
				sepmpi *mpip);

/**
 * Calculating the pair-forces acting between all particles except for 
 * the one specified. 
 * @param *ptr Pointer to array of seppart structure
 * @param type Particle type that is excluded in the calculations
 * @param cf  The cut-off length
 * @param *fun Pointer to the pair potential function.
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
  */
double sep_mpi_force_pair_exclude(seppart *ptr,  const char type, 
				  double cf, double (*fun)(double, char), 
				  sepmpi *mpip);


/**
 * Calculating the pair-forces acting between all particles using the
 * WCA potential except for the one specified. 
 * @param *ptr Pointer to array of seppart structure
 * @param type Particle type that is excluded in the calculations
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
  */
double sep_mpi_force_pair_exclude_wca(seppart *ptr,  const char type, 
				      sepmpi *mpip);


/**
 * Calculating the pair-forces acting between particles of specific 
 * types using the WCA potential
 * @param *ptr Pointer to array of seppart structure
 * @param *types String specifying the TWO particles type
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
 */
double sep_mpi_force_pair_types_wca(seppart *ptr,  const char *types, 
				    sepmpi *mpip);


/**
 * Calculating the pair-forces acting between all particles using the
 * Lennard-Jones potential except for the one specified. 
 * @param *ptr Pointer to array of seppart structure
 * @param type Particle type that is excluded in the calculations
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
  */
double sep_mpi_force_pair_exclude_lj(seppart *ptr,  const char type, 
				     sepmpi *mpip);


/**
 * Calculating the pair-forces acting between particles of specific 
 * types using the Lennard-Jones potential
 * @param *ptr Pointer to array of seppart structure
 * @param *types String specifying the TWO particles type
 * @param *mpip The sepmpi structure 
 * @return Sum of the potential energies
 */
double sep_mpi_force_pair_types_lj(seppart *ptr,  const char *types, 
				   sepmpi *mpip);

/**
 * Calculates the "gitter-force". Usefull when including wall 
 * composed of particles.
 * @param *ptr Pointer to array of seppart structure
 * @param type Label of particles
 * @param *fun Pointer to the potential
 * @param *mpip Pointer to the sepmpi structure
 * @return The average potential energy 
 */
double sep_mpi_force_x0(seppart *ptr, char type, 
		      double (*fun)(double, char), sepmpi *mpip);
				
	
/* Integrations schemes */


/**
 * Integrates the particles forward in time using the leap-frog
 * scheme.
 * @param *ptr Pointer to array of seppart structure
 * @param type Label of particles that are integrated forward
 * @param dt Step length
 * @param *mpip Pointer to the sepmpi structure  
 * @return The average square velocity 
 */
double sep_mpi_leapfrog_type(seppart *ptr, const char type, double dt, 
			   sepmpi *mpip);


/**
 * Integrates the particles forward in time using the 
 * Nose-Hoover scheme - for NVT sims.
 * @param *ptr Pointer to array of seppart structure
 * @param type Label of particles that are integrated forward
 * @param Td Desired temperature
 * @param *nu Pointer to the reservoir "friction"
 * @param Q Reservoir "effective mass"
 * @param dt Step length
 * @param *mpip Pointer to the sepmpi structure  
 * @return The average square velocity 
 */
double sep_mpi_nosehoover_type(seppart *ptr, char type, double Td, 
			     double *nu, double Q, double dt, 
			     sepmpi *mpip);


/* Miscellaneous */

/** 
 * Writes error to stderr and exists using MPI_Abort
 * @param *str Error message
 */
void sep_mpi_error(char *str, ...);
	
/**
 * Evaluates the momentum in the hole system. Process zero collects
 * the overall result.
 * @param *ptr Pointer to array of seppart structure
 * @param *mpip Pointer to the sepmpi structure
 */
double sep_mpi_eval_mom(seppart *ptr, sepmpi *mpip);

/**
 * Saves positions of particles of a certain type. 
 * @param *ptr Pointer to array of seppart structur
 * @param type The label of the particles 
 * @param file[] File where the positions are saved
 * Notice that the file is augmented with process number and that if 
 * the file exists it is overwritten
 * @param *mpip Pointer to the sepmpi structure
 */
void sep_mpi_save_pos(seppart *ptr, char type, const char file[], 
		       sepmpi *mpip);

/** 
 * Saves the positions of particles in xyz-format. All data is send to
 * process zero and written to the file from here. The file is augmented 
 * with '.xyz'.
 * @param *ptr Pointer to array of seppart structure
 * @param *partnames Particle types to be written
 * @param *preamble Comments or preamble in file
 * @param *file File name (without *.xyz extension)
 * @param *mpip Pointer to the sepmpi structure  
 */
void sep_mpi_save_xyz(seppart *ptr, const char *types, 
		      const char *preamble, const char *file, 
		      sepmpi *mpip);


#ifndef DOXYGEN_SKIP
/**
 * Collects vectors and make average element wise. All processes
 * do this. 
 * @param *vec Pointer to the vector  
 * @param length Length of vector
 * @param *mpip Pointer to the sepmpi structure
 */
void sep_mpi_average_vectors(double *vec, int length, sepmpi *mpip);
#endif


#endif
